// PageManager.cpp

#ifndef _PAGEMANAGER_CPP_
#define _PAGEMANAGER_CPP_


#include"PageManager.h"


/* 存储管理核心类前调声明 */
class MManage::FileController;
class MManage::GroupInfo;
class MManage::PageInfo;

/* 页面/组容量参数 注意参数间相互的制约关系 */

//单个页面的大小(单位:字节)
const int MManage::PageSize_Numofubeta8 = 16384;

//单个页面内组的个数
const int MManage::Group_NumInPage = 58;

//单个组的大小(单位:字节)
const int MManage::GroupSize = 280;

//单个页面前缀区大小(单位:字节)
const int MManage::PrefixSize = 72;

//单个页面后缀区大小(单位:字节)
const int MManage::SuffixSize = 72;

//页面池最大容量
const int MManage::MaxPages = 10;

//单个组内数据的最大容量(单位:字节)
const int MManage::MaxDataContext_perGroup = 276;


/*
底层文件操作封装
负责页面在文件中的大规模操作
*/

MManage::FileController::FileController(const char* tbname){
    //复制文件名
    memset(name,0,sizeof(name));
    memcpy(this->name,tbname,strlen(tbname));
    //打开文件
    if(this->__open() < 0){
        //文件打开错误
        printf("[error]-[FileController]:Construct Error\n");
    }else{
        printf("[state]-[FileController]:Construct Success\n");
    }
}



// 打开表文件(内部函数)
// 成功:0 并设置类内文件描述符
// 失败:-1 并设置类内文件描述符为-1
int MManage::FileController::__open(){
    //注意 该类只允许获取只读的数据库文件
    int res = open(this->name,O_RDWR);
    if(res < 0){
        this->__file_fd = -1;
        printf("[error]-[FileController]:open file return < 0\n");
        return -1;
    }
    this->__file_fd = res;
    this->__realsize = lseek(this->__file_fd,0,SEEK_END);
    this->pagenum = this->__realsize / PageSize_Numofubeta8;
    return 0;
}

// PageIndex => offset
__off_t MManage::FileController::__get_offset(int pageIndex){
    return pageIndex * PageSize_Numofubeta8;
}

// offset => PageIndex
int MManage::FileController::__get_PageIndex(__off_t offSet){
    return offSet / PageSize_Numofubeta8;
}

// 写函数:覆盖写一个页面 页面信息在pointer指向的页面空间中
// 成功:0 失败:-1
int MManage::FileController::writePage(const ubeta8 pageIndex,const ubeta8* pointer,int wtsize){
    if(__exist_Page(pageIndex)){
        //将数据写入文件并保存
        lseek(this->__file_fd,this->__get_offset(pageIndex),SEEK_SET);
        //将整个页面写入文件
        wtsize = std::min(wtsize,PageSize_Numofubeta8);//限制读写大小
        int writelen = write(this->__file_fd,pointer,wtsize);
        printf("[report]-[FileController]:writePage():writelen=%d\n",writelen);
        //页面头尾限制标志
        __init_PageSpace(pageIndex);
        //同步文件状态
        this->Self_Sync();
        return 0;
    }
    //页面不存在
    return -1;
}

// 读函数:根据pageIndex指定的页面号将数据写入指定的data内存中
// 成功:0 读取内容不会超过一个页面大小
// 失败:-1
int MManage::FileController::readPage(const ubeta8 pageIndex,ubeta8* data,int rdsize){
    if(__exist_Page(pageIndex)){
        lseek(this->__file_fd,this->__get_offset(pageIndex),SEEK_SET);
        //将数据从文件读出-这里有依次读取整个页面的操作
        rdsize = std::min(rdsize,PageSize_Numofubeta8);
        int readlen = read(this->__file_fd,data,rdsize);
        printf("[report]-[FileController]:readPage():readlen=%d\n",readlen);
        return 0;
    }
    //页面不存在
    return -1;
}

//检查对应页面号的文件空间是否存在
int MManage::FileController::__exist_Page(const ubeta8 pageIndex){
    return this->pagenum > (int)pageIndex;
}

int MManage::FileController::__init_PageSpace(int pageIndex){
    char begin_char[3] = {"$"};
    char end_char[3] = {"#"};
    int res = 0;
    //定位到指定偏移值
    res = lseek(this->__file_fd,this->__get_offset(pageIndex),SEEK_SET);
    if(res < 0){
        printf("[error]-[PageController]:__init_PageSpace():lseek1() failed\n");
        return -1;
    }
    //写空间头标志
    write(this->__file_fd,begin_char,1);//page_head
    //定位到页面尾部
    res = 0;
    res = lseek(this->__file_fd,this->__get_offset(pageIndex+1)-1,SEEK_SET);
    if(res < 0){
        printf("[error]-[PageController]:__init_PageSpace():lseek2() failed\n");
        return -1;
    }
    //写空间尾标志
    write(this->__file_fd,end_char,1);//page_tail
    return 0;
}

//在文件中向后添加一个新的页面并初始化基本信息
int MManage::FileController::__alloc_Back(){
    this->pagenum++;
    //移动offset以增添新的页面
    this->__realsize = lseek(this->__file_fd,(this->pagenum)*PageSize_Numofubeta8,SEEK_SET);
    //初始化页面头尾信息
    this->__init_PageSpace(this->pagenum-1);//初始化页面头尾
    //同步文件状态
    this->Self_Sync();
}

// 删除文件中的最后一个页面的空间
// 成功:0
// 失败:-1
int MManage::FileController::__delet_Back(){
    //评估删除操作合理性
    if(pagenum <= 1) { return -1; }
    //文件长度截断
    __off_t new_lenth = (this->pagenum-1) * (__off_t)PageSize_Numofubeta8;
    int res = ftruncate(this->__file_fd,new_lenth);
    if(res < 0){
        printf("[error]-[FileController]:__delet_Back() ftruncate failed.\n");
        return -1;
    }
    //文件内容同步
    this->Self_Sync();
    //更新类内部记录数据
    this->pagenum--;
    this->__realsize = new_lenth;
}

//将某块页面的内容拷贝到其他页面上
//该函数直接覆盖内容 不做页面数据逻辑有效性检测
int MManage::FileController::__copy_Space(int from_pageIndex,int to_pageIndex){
    //拷贝预处理
    ubeta8* buffer = (ubeta8*)malloc(PageSize_Numofubeta8 * sizeof(ubeta8));
    //拷贝操作
    this->readPage(from_pageIndex,buffer);
    this->writePage(to_pageIndex,buffer,PageSize_Numofubeta8);
    free(buffer);
}

//关闭文件描述符
void MManage::FileController::__close(){
    if(this->__file_fd != -1){
        this->Self_Sync();//数据同步
        close(this->__file_fd);
        this->__file_fd = -1;
        memset(this->name,0,sizeof(this->name));
        this->pagenum = 0;
        this->__realsize = 0;
    }
}

//文件内容同步到磁盘
int MManage::FileController::Self_Sync(){
    return fsync(this->__file_fd);
}


/*
[组对象]只是保存页面中的组在内存中的位置
它同自己相应的[页面对象]共生死
它只提供解析功能和修改功能
*/

MManage::GroupInfo::GroupInfo(ubeta8* grpos = nullptr){
    this->inner_pointer = grpos;
}
MManage::GroupInfo::~GroupInfo() { this->inner_pointer = nullptr; }


const ubeta8 MManage::GroupInfo::FULL_UBETA8 = 0xFF;
const ubeta16 MManage::GroupInfo::FULL_UBETA16 = 0xFFFF;

//是否分配
bool MManage::GroupInfo::isDistri() {
    return (*inner_pointer) & 0b10000000;
}

void MManage::GroupInfo::setDistri(bool stat = false) {
    ubeta8 pold = *inner_pointer;
    if(stat){
        pold = (pold & 0b01111111) + 0b10000000;
    }else{
        pold = pold & 0b01111111;
    }
    *inner_pointer = pold;
}

//组编号-ubeta8低6位有效
ubeta8 MManage::GroupInfo::getGroupIndex() {
    return ((*inner_pointer)>>1) & 0b00111111;
}

void MManage::GroupInfo::setGroupIndex(ubeta8 index) {
    index = (index << 1) & 0b01111110;
    ubeta8 old = *inner_pointer;
    ubeta8 newindex = (old & 0b10000000) + index + (old & 0b00000001);
    *inner_pointer = newindex;
}

//后一组编号-ubeta8低6位有效
ubeta8 MManage::GroupInfo::getNextIndex() {
    ubeta8 pre = (*inner_pointer);
    pre &= 0b00000001;
    ubeta8 lat = *(inner_pointer+1);
    lat &= 0b11111000;
    return (pre<<5)+(lat>>3);
}

void MManage::GroupInfo::setNextIndex(ubeta8 index) {
    ubeta8 pre = (index & 0b00100000) >> 5;
    pre = pre + ( (*inner_pointer) & 0b11111110 );
    *inner_pointer = pre;
    //
    ubeta8 lst = (index & 0b00011111) << 3;
    lst = lst + (*(inner_pointer+1) & 0b00000111);
    *(inner_pointer+1) = lst;
}

//前一组编号-ubeta8低6位有效
ubeta8 MManage::GroupInfo::getLastIndex() {
    ubeta8 pre = *(inner_pointer+1);
    pre &= 0b00000111;
    ubeta8 lat = *(inner_pointer+2);
    lat &= 0b11100000;
    return (pre<<3)+(lat>>5);
}

void MManage::GroupInfo::setLastIndex(ubeta8 index) {
    ubeta8 pre = (index & 0b00111000) >> 3;
    pre = pre + ( *(inner_pointer+1) & 0b11111000 );
    *(inner_pointer+1) = pre;
    //
    ubeta8 lst = (index & 0b00000111)  << 5;
    lst = lst + ( *(inner_pointer+2) & 0b00011111 );
    *(inner_pointer+2) = lst;
}

//空白数据-ubeta8低4位有效
ubeta8 MManage::GroupInfo::getSpInfo() {
    ubeta8 info = *(inner_pointer+2);
    info &= 0b00011110;
    return (info>>1);
}

void MManage::GroupInfo::setSpInfo(ubeta8 info) {
    ubeta8 old = *(inner_pointer+2);
    info = info & 0b00001111;
    ubeta8 newinfo = (old & 0b11100001) + (info << 1);
    *(inner_pointer+2) = newinfo;
}

//数据区总长度-ubeta16低9位有效
ubeta16 MManage::GroupInfo::getDataLenth() {
    ubeta16* temp = (ubeta16*)(inner_pointer + 2);
    ubeta16 len = (*temp) & 0x01FF;
    return len;
}

void MManage::GroupInfo::setDataLenth(ubeta16 lenth) {
    ubeta16* temp = (ubeta16*)(inner_pointer + 2);
    ubeta16 len = (*temp) & 0xFE00;
    len = (lenth & 0x01FF) + len;
    *(inner_pointer+2) = len;
}

//分配标志位(1) + 组号(6) + 后置组编号(6) + 前置组编号(6) + 空白(4) + 数据段总长(9) + 存储段(276B)
// 写数据
// 返回实际写入的数据长度
ubeta16 MManage::GroupInfo::writeData(const ubeta8* data,int wtsize){
    ubeta16 real_wtsize = (ubeta16)std::min(MaxDataContext_perGroup,wtsize);
    ubeta8* pointer = this->inner_pointer + 32;
    memcpy(pointer,data,real_wtsize);
    //不再刷新数据段空余空间
    this->setDataLenth(real_wtsize);
    return real_wtsize;
}

// 读取数据
// 返回实际读取的数据长度
ubeta16 MManage::GroupInfo::readData(ubeta8* data){
    if(this->isDistri()){
        ubeta16 len = this->getDataLenth();
        memcpy(data,this->inner_pointer+32,len);
        return len;
    }
    return 0;
}




/*
空间的申请权限在PageInfo类中
只有该类能够调用malloc()函数
PageIndex在文件内是唯一的
*/


MManage::PageInfo::PageInfo(const ubeta8 PageIndex,FileController* tbfer=nullptr){
    this->data_pointer = nullptr;
    this->modify_cnt = 0;
    //指定页面编号
    this->PageIndex = PageIndex;
    //申请新的空间
    this->mm_space = (ubeta8*)malloc(sizeof(ubeta8)*PageSize_Numofubeta8);
    memset(this->mm_space,0,sizeof(this->mm_space));//清空页面内存空间
    //询问文件数据存在性
    this->table_fcntler = tbfer;
    if(this->table_fcntler){
        //存在页面实体并读取
        if(this->table_fcntler->__exist_Page(this->PageIndex)){
            int res = this->table_fcntler->readPage(this->PageIndex,this->mm_space,PageSize_Numofubeta8);
            if(res < 0){
                printf("[error]-[PageInfo]-PageInfo():Index(%d) Construct readPage error\n",PageIndex);
            }
        }
    }
    //重写内存空间开头存放的页面标号
    char buf[10];
    memset(buf,0,sizeof(buf));
    sprintf(buf,"$%d$",this->PageIndex);
    memcpy(this->mm_space,buf,sizeof(char)*strlen(buf));
    //初始化页面区域划分指针
    this->mm_grp = this->mm_space + PrefixSize;
    this->mm_backspace = this->mm_grp + Group_NumInPage * GroupSize;
    printf("[report]-[PageInfo]-PageInfo():init mem_pointers\n");
    //验证组存在性并记录使用情况
    memset(vis,0,sizeof(vis));
    this->space_grp_cnt = Group_NumInPage;
    for(int i=0;i<Group_NumInPage;i++){
        this->grplis[i] = this->mm_grp + i * GroupSize;
        if(GroupInfo(this->grplis[i]).isDistri()){
            this->vis[i] = 1;
            this->space_grp_cnt--;
        }
    }
    printf("[report]-[PageInfo]-PageInfo():page[%d]-grp_used:%d/%d\n",this->PageIndex,this->space_grp_cnt,Group_NumInPage);
};

//资源释放
int MManage::PageInfo::__release(){
    //同步到文件实体
    this->Self_Sync();
    //释放内存
    if(this->mm_space) free(this->mm_space);
    this->mm_space = nullptr;
    if(this->data_pointer) free(this->data_pointer);
    this->data_pointer = nullptr;
    return 0;
}

//周期性同步到文件实体
void MManage::PageInfo::round_Sync(){
    if(this->table_fcntler){//保证FileController的存在性
        this->modify_cnt = (this->modify_cnt + 1) % this->sync_round;
        if(this->modify_cnt == 0){
            printf("[report]-[PageInfo]-round_Sync():One Call Sync()\n");
            int res = 0;
            res = this->table_fcntler->writePage(this->PageIndex,this->mm_space,PageSize_Numofubeta8);
            printf("[error]-[PageInfo]-round_Sync():Sync without File-Entity\n");
        }
    }
}

//同步到文件实体
void MManage::PageInfo::Self_Sync(){
    //将数据写入页面
    if(this->table_fcntler){//保证FileController的存在性
        int res = 0;
        res = this->table_fcntler->writePage(this->PageIndex,this->mm_space,PageSize_Numofubeta8);
        printf("[error]-[PageInfo]-round_Sync():Sync without File-Entity\n");
    }
}

MManage::PageInfo::~PageInfo(){
    this->__release();
};


/* 单个组的分配与回收 */

// [1]使得组有效-将标记区清空-对象必须是无效组
// 错误:指定的组已经被有效化 -1
// 错误:指定的组不存在 -2
// 成功:0
int MManage::PageInfo::__DistriGroup(const ubeta8 groupIndex){
    if(groupIndex < Group_NumInPage){
        if(this->vis[groupIndex]){
            //尝试有效化已经被分配的组-操作错误
            return -1;
        }
        //设置PageInfo状态参数
        this->vis[groupIndex] = 1;
        this->space_grp_cnt--;
        //初始化内存中组的相关标记设置
        GroupInfo ginfo = GroupInfo(this->grplis[groupIndex]);
        ginfo.setDistri(true);
        ginfo.setGroupIndex(groupIndex);
        ginfo.setLastIndex(GroupInfo::FULL_UBETA8);
        ginfo.setNextIndex(GroupInfo::FULL_UBETA8);
        ginfo.setSpInfo(0);
        ginfo.setDataLenth(0);
        //周期性同步
        this->round_Sync();
        return 0;
    }
    return -2;
}


// [2]删除单个有效组
// 错误:指定的组已经被有效化 -1
// 错误:指定的组不存在 -2
// 成功:0
int MManage::PageInfo::__inDistriGroup(const ubeta8 groupIndex){
    if(groupIndex < Group_NumInPage){
        if(this->vis[groupIndex]){
            return -1;
        }
        GroupInfo(this->grplis[groupIndex]).setDistri(false);
        this->vis[groupIndex] = 0;
        this->space_grp_cnt++;
        //周期性同步
        this->round_Sync();
        return 0;
    }
    return -2;
}


/* 完整组链的查找 */

// 根据单个结点获取整条组链
// 失败: -1 指定的组编号无效
// 失败: -2 指定的组无效
// 成功: 0
int MManage::PageInfo::__getGroupList(const ubeta8 nodeIndex,GrpList& result_lis){
    //检查当前结点的编号有效性
    if(nodeIndex >= Group_NumInPage){
        return -1;
    }
    //验证组的有效性
    if(!this->vis[nodeIndex]){
        return -2;
    }
    //循环获取组链信息
    GrpList lis = {nodeIndex};
    //前向组
    ubeta8 pre = nodeIndex;
    while(1){
        pre = GroupInfo(this->grplis[pre]).getLastIndex();
        //前向寻找结束
        if(pre == GroupInfo::FULL_UBETA8) break;
        //验证前向组有效性
        if(GroupInfo(this->grplis[pre]).isDistri()){
            //加入组链
            lis.push_front(pre);
        }else{
            break;
        }
    }
    //后向组
    ubeta8 nxt = nodeIndex;
    while(1){
        nxt = GroupInfo(this->grplis[nxt]).getNextIndex();
        //后向寻找结束
        if(nxt == GroupInfo::FULL_UBETA8) break;
        //验证后向组有效性
        if(GroupInfo(this->grplis[nxt]).isDistri()){
            //加入组链
            lis.push_back(nxt);
        }else{
            break;
        }
    }
    result_lis = lis;//更新结果并返回
    return 0;
}
    
/* 组链的创建与删除 */

// 设置已分配的组链的标记以使其串联-调用前应先使组有效化
int MManage::PageInfo::__initGroupList(const GrpList lis){
    int lenth = lis.size();
    for(int i=0;i<lenth;i++){
        //获取组下标
        ubeta8 curIndex = lis[i];
        GroupInfo ginfo = GroupInfo(this->grplis[curIndex]);
        //前置标记
        ginfo.setLastIndex( i == 0 ? GroupInfo::FULL_UBETA8 : lis[i-1] );
        //后置标记
        ginfo.setNextIndex( i == lenth - 1 ? GroupInfo::FULL_UBETA8 : lis[i+1] );
    }
    //周期性同步
    this->round_Sync();
    return 0;
}

// 分配指定个数的组并形成组链
// 失败:-1 没有足够的页面空间可供分配
// 成功:0
int MManage::PageInfo::__alloc_GrpList(int alloc_num,GrpList& result_lis){
    GrpList lis;
    //检查空闲组个数
    if(this->space_grp_cnt >= alloc_num){
        int cur_cnt = 0;
        for(int i=0;i<Group_NumInPage&&cur_cnt<alloc_num;i++){
            if(!this->vis[i]){
                //尝试分配该组
                int res = this->__DistriGroup(i);
                if(res == 0){
                    //分配成功
                    lis.push_back(i);
                    cur_cnt++;
                }
            }
        }
        //数据分配结果报告
        int lenth = lis.size();
        printf("[report]-[PageInfo]-__alloc_GrpList():real_alloc_num=%d\n",lenth);
        //指明分配结果
        result_lis = lis;
        //组链初始化
        this->__initGroupList(lis);
        return 0;
    }
    return -1;
}

// [3]组链删除
// 失败: -1 组链获取失败
// 失败: -2 循环删除失败
// 成功: 0
int MManage::PageInfo::__deleteGroupList(const ubeta8 nodeIndex){
    GrpList lis;
    int res = this->__getGroupList(nodeIndex,lis);
    //组链获取失败
    if(res < 0) return -1;
    //循环删除组链中的组
    int lenth = lis.size();
    for(int i=0;i<lenth;i++){
        res = this->__inDistriGroup(lis[i]);
        if(res < 0){
            //循环删除失败
            return -2;
        }
    }
    return 0;
}

/* 组链的读写 */

// 直接向组链中写入数据
void MManage::PageInfo::__direct_write(GrpList lis,const ubeta8* data,int wtsize){
    //依次向组内写入数据
    int cur = 0;
    int lenth = lis.size();
    for(int i=0;i<lenth&&cur<lenth;i++){
        //向单个组写入数据
        cur += GroupInfo(this->grplis[lis[i]]).writeData(data+cur,wtsize-cur);
    }
    //周期性同步
    this->round_Sync();
}

// 写特定的组涉及到的组链
// 失败: -1 没有找到指定组所在的组链
// 失败: -2 组链延长操作失败
// 失败: 1  空间不足需要请求其他页面(不会删除现有的存储空间)
// 成功: 0
int MManage::PageInfo::Write(const ubeta8 GroupIndex,const ubeta8* data,int wtsize){
    //检查覆写数据所需组数
    int need_num = wtsize / MaxDataContext_perGroup;
    if(need_num * MaxDataContext_perGroup < wtsize) { need_num++; }
    //获取组链
    GrpList lis;
    int res = this->__getGroupList(GroupIndex,lis);
    if(res < 0) { return -1; }
    int cur_num = lis.size();
    //组链比较
    if(cur_num == need_num){
        //直接覆盖写
        this->__direct_write(lis,data,wtsize);
    }else if(cur_num > need_num){
        //缩减组链长度后写入数据
        int lenth = cur_num;
        while(lenth > need_num){
            //无效化尾部组
            this->__inDistriGroup(lis[lenth-1]);
            lis.pop_back();
            lenth--;
        }
        //设置尾部标记
        GroupInfo(this->grplis[lis[lenth-1]]).setNextIndex(GroupInfo::FULL_UBETA8);
        //写入数据
        this->__direct_write(lis,data,wtsize);
    }else if(cur_num < need_num){
        int else_need = need_num - cur_num;
        if(else_need > this->space_grp_cnt){
            //空间不足需要请求其他页面
            printf("[warn]-[PageInfo]-Write(index):no more empty-group\n");
            return 1;
        }else{
            //延长组链后写
            GrpList newlis;
            res = this->__alloc_GrpList(else_need,newlis);
            if(res < 0){
                printf("[error]-[PageInfo]-Write(index):GroupList extend failed\n");
                return -2;
            }
            //生成新的组链
            int lenth = newlis.size();
            for(int i=0;i<lenth;i++){
                lis.push_back(newlis[i]);
            }
            //更新组链标记
            this->__initGroupList(lis);
            //写入数据
            this->__direct_write(lis,data,wtsize);
        }
    }
    return 0;
}

// 写数据到页面
// 失败: -1 空闲组不满足数据存储大小
// 失败: -2 分配组链失败
// 成功: 0 返回分配的索引Index
int MManage::PageInfo::Write(const ubeta8* data,int wtsize,Index& result_index){
    printf("[report]-[PageInfo]-Write():PageIndex=%d\n",this->PageIndex);
    //检验长度大小与空闲组关系
    int need_num = wtsize / MaxDataContext_perGroup;
    if(need_num * MaxDataContext_perGroup < wtsize) { need_num++; }
    if(need_num > this->space_grp_cnt){
        return -1;
    }
    //分配组链
    GrpList lis;
    int res = this->__alloc_GrpList(need_num,lis);
    if(res < 0){
        //组链分配失败
        printf("[error]-[PageInfo]-Write():GroupList alloc failed\n");
        return -2;
    }
    //依次向组内写入数据
    this->__direct_write(lis,data,wtsize);
    printf("[report]-[PageInfo]-Write():data has-been writen\n");
    //汇报分配结果
    result_index.page_index = this->PageIndex;
    result_index.group_index = lis[0];
    return 0;
}

/* 数据读取 */
// 数据读取准备-该函数可连续调用 但 最后必须调用Read_Over()回收内存
// 成功:返回准备好的数据长度-数据准备在了对象的this->data_pointer指向的空间中
// 失败: -1 没有找到组链
int MManage::PageInfo::Read_Ready(const ubeta8 groupIndex){
    //删除原有的可能存在的已分配碎片内存
    if(this->data_pointer){
        free(this->data_pointer);
        this->data_pointer = nullptr;
    }
    //获取组链
    GrpList lis;
    int res = this->__getGroupList(groupIndex,lis);
    if(res < 0){
        printf("[error]-[PageInfo]-Read():no group(%d) in page(%d)\n",groupIndex,PageIndex);
        return -1;
    }
    //准备数据读写缓冲区
    int cur = 0;
    int lenth = lis.size();
    int bufsize = MaxDataContext_perGroup * lenth;
    //为对象指针赋予空间
    this->data_pointer = (ubeta8*)malloc(sizeof(ubeta8)*bufsize);
    //拷贝数据
    for(int i=0;i<lenth;i++){
        GroupInfo ginfo = GroupInfo(this->grplis[lis[i]]);
        cur += ginfo.readData(this->data_pointer+cur);
    }
    return cur;
}

//数据读取完毕后用于回收对象所有的数据缓冲区
void MManage::PageInfo::Read_Over(){
    if(this->data_pointer){
        free(this->data_pointer);
    }
    this->data_pointer = nullptr;
    /*由于每个对象会在读取数据时分别开辟空间并添加到自身的data_pointer指针上
    所以每次读取原则上都应当先malloc后free,即调用Read_Over()回收空间
    由于data_pointer在对象存活期内认定为[非空时表示指向了被分配的空间]
    所以该类也在[构造函数]、[析构函数]、[Read_Ready函数开头]分别添加了[非空检测则回收]的机制
    事实上，只要该类的某个对象能够完整的经历生存期和析构过程
    即便上层没有主动调用Read_Over函数 仍能够避免碎片内存*/
}



#endif // _PAGEMANAGER_CPP_


